package com.suncky.frame.base.adapter;

import android.content.Context;
import android.util.SparseArray;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.BaseAdapter;

import androidx.annotation.NonNull;

import com.suncky.frame.base.adapter.holder.ViewHolder;
import com.suncky.frame.base.adapter.listener.ListAdapterListener;

import java.util.ArrayList;
import java.util.List;

/**
 * 通用列表适配器
 * Created by HY_PC on 2018 11/21 0021 17:21.
 */
public abstract class ListAdapter<T> extends BaseAdapter implements ViewHolder.ViewEventListener {
    protected Context mContext;
    protected List<T> mDatas;
    protected final int mItemLayoutId;
    protected ListAdapterListener mListener;
    protected int mPosition = -1;
    protected SparseArray<ViewHolder> viewHolders;

    public ListAdapter(Context context) {
        this(context, null);
    }

    public ListAdapter(Context context, List<T> data) {
        this(context, data, 0);
    }

    public ListAdapter(Context context, List<T> data, int itemLayoutId) {
        this(context, data, itemLayoutId,null);
    }

    public ListAdapter(Context context, List<T> data, int itemLayoutId, ListAdapterListener listener) {
        this.mContext = context;
        this.mDatas = data;
        this.mItemLayoutId = itemLayoutId;
        this.viewHolders = new SparseArray<>();
        this.mListener = listener;
    }

    /**
     * 获取位置下的ViewHolder
     * @param position
     * @return
     */
    public ViewHolder getViewHolder(int position) {
        return viewHolders.get(position);
    }

    /**
     * 获取标记位置
     * @return
     */
    public int getPosition() {
        return mPosition;
    }

    /**
     * 设置标记位置
     * @param position
     */
    public void setPosition(int position) {
        this.mPosition = position;
    }

    /**
     * 获取标记位置下的数据
     * @return
     */
    public T getPositionItem(){
        return getItem(mPosition);
    }

    /**
     * 刷新标记位置
     * @param position
     */
    public void refresh(int position) {
        setPosition(position);
        notifyDataSetChanged();
    }

    /**
     * 设置adapter监听
     * @param listener
     */
    public void setListener(ListAdapterListener listener){
        this.mListener = listener;
    }

    /**
     * 设置数据源
     *
     * @param data
     */
    public void setData(List<T> data) {
        mDatas = data;
        notifyDataSetChanged();
    }

    /**
     * 设置数据源及标记位置
     *
     * @param data
     */
    public void setData(List<T> data, int position) {
        mDatas = data;
        mPosition = position;
        notifyDataSetChanged();
    }

    public List<T> getData() {
        return mDatas;
    }

    /**
     * 添加数据
     * @param element
     */
    public void add(T element){
        if (element == null) {
            return;
        }
        if (mDatas == null) {
            mDatas = new ArrayList<>();
        }
        mDatas.add(element);
        notifyDataSetChanged();
    }

    /**
     * 添加数据列表
     * @param elements
     */
    public void add(List<T> elements){
        if (elements == null || elements.size() == 0) {
            return;
        }
        if (mDatas == null) {
            mDatas = new ArrayList<>();
        }
        mDatas.addAll(elements);
        notifyDataSetChanged();
    }

    /**
     * 插入数据
     * @param position 插入位置
     * @param element 数据
     */
    public void insert(int position,T element) {
        if (element == null || position < 0 || position > getCount()) {
            return;
        }
        mDatas.add(position, element);
        notifyDataSetChanged();
    }

    /**
     * 插入数据列表
     *
     * @param position 插入位置
     * @param elements 数据
     */
    public void insert(int position, List<T> elements) {
        if (position < 0 || position > getCount() || elements == null || elements.size() == 0) {
            return;
        }
        mDatas.addAll(position,elements);
        notifyDataSetChanged();
    }

    /**
     * 移除指定位置的数据
     * @param position
     */
    public void remove(int position){
        if (mDatas == null || position < 0 || position >= mDatas.size()) {
            return;
        }
        mDatas.remove(position);
        notifyDataSetChanged();
    }

    /**
     * 清空数据源
     */
    public void clearData() {
        if (mDatas != null) {
            mDatas.clear();
        }
        notifyDataSetChanged();
    }

    @Override
    public int getCount() {
        return mDatas != null ? mDatas.size() : 0;
    }

    @Override
    public T getItem(int position) {
        if (mDatas == null || position < 0 || position > mDatas.size() - 1) {
            return null;
        }
        return mDatas.get(position);
    }

    @Override
    public long getItemId(int position) {
        return position;
    }

    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        final ViewHolder viewHolder = obtainViewHolder(parent, convertView, position);
        if (viewHolder == null) {
            return null;
        }
        convert(viewHolder, getItem(position), position);
        viewHolders.put(position, viewHolder);
        return viewHolder.getConvertView();
    }

    @Override
    public void onClick(View v, int position) {
        if (mListener != null) {
            mListener.onClickEvent(position, v.getId());
        }
    }

    @Override
    public void onItemClick(AdapterView<?> v, int position, int subPosition) {
        if (mListener != null) {
            mListener.onItemClickEvent(position, subPosition, v.getId());
        }
    }

    @Override
    public int getItemViewType(int position) {
        return super.getItemViewType(position);
    }

    @Override
    public int getViewTypeCount() {
        return super.getViewTypeCount();
    }

    /**
     * 获取item布局id
     * @param viewType viewType return by {@link #getItemViewType(int)}
     * @return
     */
    public int getItemLayoutId(int viewType) {
        return mItemLayoutId;
    }

    /**
     * 显示列表item数据
     * @param holder
     * @param item
     * @param position
     */
    public abstract void convert(ViewHolder holder, T item, int position);


    private ViewHolder obtainViewHolder(ViewGroup parent, View convertView, int position) {
        if (convertView == null) {
            return onCreateViewHolder(parent, position);
        }else {
            ViewHolder viewHolder = (ViewHolder) convertView.getTag();
            viewHolder.setPosition(position);
            return viewHolder;
        }
    }

    /**
     * 创建ViewHolder实例
     * @param parent
     * @param position
     * @return
     */
    public ViewHolder onCreateViewHolder(ViewGroup parent, int position) {
        int layoutId = getItemLayoutId(getItemViewType(position));
        if (layoutId == 0) {
            return null;
        }
        return new ViewHolder(LayoutInflater.from(mContext).inflate(layoutId, parent, false), position, this);
    }
}
